#include "globalconfig.h"
#include "dataparser.h"

using namespace std;

DataParser::DataParser(TRDPThread *com)
{

    for(int i=0; i<GlobalConfig::recvTRDPList.length(); ++i)
    {
        QList<unsigned long> list;
        list.clear();
        for(int j=0; j<GlobalConfig::recvTRDPList[i].node.size(); ++j)
            list.append(0);
        recvVar.append(list);

    }
    for(int i=0; i<GlobalConfig::sendTRDPList.size(); ++i)
    {
        QList<unsigned long> list;
        list.clear();
        for(int j=0; j<GlobalConfig::sendTRDPList[i].node.size(); ++j)
            list.append(0);
        sendVar.append(list);
    }
    trdp = com;
}

void DataParser::initCom()
{
    trdp->initCom();
}

unsigned long DataParser::readMemVar(int comidIndex, int byte, int bit, int size)
{
    Q_ASSERT(byte*8+bit+size <= 1000*8);
    const unsigned char *p_data_rcv=NULL;
    p_data_rcv = trdp->getRecvPointer(GlobalConfig::recvTRDPList.at(comidIndex).srcipinfo.index);

    if(p_data_rcv  == NULL)
        return 0;

    if(size < 8)
    {
        unsigned char tmp = 0;
        switch(size)
        {
        case 1: tmp = 0x01;break;
        case 2: tmp = 0x03;break;
        case 3: tmp = 0x07;break;
        case 4: tmp = 0x0f;break;
        case 5: tmp = 0x1f;break;
        case 6: tmp = 0x3f;break;
        case 7: tmp = 0x7f;break;
        default: break;
        }
        unsigned char value = p_data_rcv[byte];
        return (value>>bit) & tmp;
    }
    else if(size == 8)
        return p_data_rcv[byte];
    else if(size == 16)
        return (p_data_rcv[byte]<<8) + p_data_rcv[byte+1];
	else if(size == 24)
        return (p_data_rcv[byte]<<16) + (p_data_rcv[byte+1]<<8) + p_data_rcv[byte+2];
    else if(size == 32)
        return (p_data_rcv[byte]<<24) + (p_data_rcv[byte+1]<<16)
                + (p_data_rcv[byte+2]<<8) + p_data_rcv[byte+3];
    return 0;
}

void DataParser::writeMemVar(int comidIndex, int byte, int bit, int size, unsigned long value)
{
    Q_ASSERT(byte*8+bit+size <= 1000*8);
    //printf("comidindex=%d,byte=%d,bit=%d,size=%d,value=%d\n",comidIndex,byte,bit,size,value);
    if(size < 8)
    {
        unsigned char tmp = 0;
        for(int i=0; i<8; ++i)
        {
            if(i>=bit && i<bit+size)
                continue;
            tmp += (0x01<<i);
        }
        unsigned char val = (trdp->getSendPointer(comidIndex))[byte];
        val &= tmp;
        (trdp->getSendPointer(comidIndex))[byte] = (value<<bit) + val;
    }
    else if(size == 8)
        (trdp->getSendPointer(comidIndex))[byte] = value;
    else if(size == 16)
    {
        (trdp->getSendPointer(comidIndex))[byte] = value >> 8;
        (trdp->getSendPointer(comidIndex))[byte+1] = value;
    }
    else if(size == 32)
    {
        (trdp->getSendPointer(comidIndex))[byte] = value >> 24;
        (trdp->getSendPointer(comidIndex))[byte+1] = value >> 16;
        (trdp->getSendPointer(comidIndex))[byte+2] = value >> 8;
        (trdp->getSendPointer(comidIndex))[byte+3] = value;
    }
}

void* DataParser::parserThread(void *arg)
{
    cout << "parser thread start" << endl;
    DataParser *parser = (DataParser *)arg;
    const unsigned char *hbptr = NULL;
    uint cycle_count = 0;
    while(parser->xParseState && parser->trdp->getComState()==TRDPThread::running)
    {
        if(parser->trdp->getComState()==TRDPThread::running)
        {
            for(int i=0; i<GlobalConfig::recvTRDPList.size(); i++)
            {
                //判断心跳
                hbptr = parser->trdp->getRecvPointer(GlobalConfig::recvTRDPList.at(i).srcipinfo.index);
                uint16_t hbvalue = (hbptr[0]<<8) + hbptr[1];

                if(hbvalue != GlobalConfig::recvTRDPList.at(i).srcipinfo.preHBvalue)
                {
                    GlobalConfig::recvTRDPList[i].srcipinfo.preHBvalue = hbvalue;
                    GlobalConfig::recvTRDPList[i].srcipinfo.xHBnormal = true;
                    GlobalConfig::recvTRDPList[i].srcipinfo.HBcounter = 0;
                }
                else
                    GlobalConfig::recvTRDPList[i].srcipinfo.HBcounter++;

                if(GlobalConfig::recvTRDPList[i].srcipinfo.HBcounter >  8)
                {
                    GlobalConfig::recvTRDPList[i].srcipinfo.xHBnormal = false;
                }
                uint16_t times_of_base_cycle = GlobalConfig::recvTRDPList[i].period/MINMUM_CYCLE;
                //qDebug()<<"comid:"<<GlobalConfig::recvTRDPList[i].comid<<" cyclecount:"<<cycle_count<<"times of base:"<<times_of_base_cycle<<" division:"<<cycle_count % times_of_base_cycle;
                if((cycle_count % times_of_base_cycle) != 0 )
                    continue;
                for(int j=0; j<parser->getRecvVarCount(i); j++)
                {
                    unsigned long value = parser->readMemVar(i, parser->getRecvVarByte(i, j), parser->getRecvVarBit(i, j), parser->getRecvVarSize(i, j));
                    parser->setRecvVarValue(i, j, value);
                }
            }
            cycle_count++;
            cycle_count = cycle_count%100;
        }
        usleep(MINMUM_CYCLE*1000);
    }
    cout  << "parser thread end" << endl;
    return NULL;
}

TRDPThread * DataParser::getTRDPThread()
{
    return trdp;
}

void DataParser::startCom()
{
    trdp->startCom();
}

void DataParser::stopCom()
{
    trdp->stopCom();
}

int DataParser::getComState()
{
    return trdp->getComState();
}

void DataParser::startParser()
{
#ifdef RUN_IN_BOARD
    xParseState = true;
    pthread_t pid;
    pthread_create(&pid, NULL, parserThread, (void*)this);
#endif
}

void DataParser::stopParser()
{
    xParseState = false;
}

void DataParser::setSendVarValue(int comidIndex, int index, unsigned long value)
{
    Q_ASSERT(comidIndex>=0 && comidIndex<GlobalConfig::sendTRDPList.size());

    if(trdp->getComState() == TRDPThread::running)
    {
        if(sendVar[comidIndex].at(index) != value)
        {
            sendVar[comidIndex][index] = value;
            writeMemVar(comidIndex, getSendVarByte(comidIndex, index), getSendVarBit(comidIndex, index), getSendVarSize(comidIndex, index), value);
            if(index>0)
                qDebug()<<"set send var value by byte and bit:"<<comidIndex<<" "<<index<<" "<<value;
        }
    }
}

void DataParser::setSendVarValue(int comidIndex, uint byte, uint bit, unsigned long value)
{
    Q_ASSERT(comidIndex>=0 && comidIndex<GlobalConfig::sendTRDPList.size());

//    qDebug()<<" send var value by byte and bit:"<<comidIndex<<" "<<byte<<" "<<bit<<" "<<value;
    int index = getSendVarIndex(comidIndex,byte,bit);
    if(trdp->getComState() == TRDPThread::running && index>=0)
    {
        if(sendVar[comidIndex].at(index) != value)
        {
            sendVar[comidIndex][index] = value;
            pthread_mutex_lock(&trdp->trdp_send_mutex);
            writeMemVar(comidIndex, getSendVarByte(comidIndex, index), getSendVarBit(comidIndex, index), getSendVarSize(comidIndex, index), value);
            pthread_mutex_unlock(&trdp->trdp_send_mutex);
        }
    }
}

unsigned long DataParser::getSendVarValue(int comidindex, int index)
{
    return sendVar[comidindex].at(index);
}

void DataParser::setRecvVarValue(int comidIndex, int index, unsigned long value)
{
    if(value != recvVar[comidIndex].at(index))
    {
        recvVar[comidIndex][index] = value;
        int varoffset = getRecvVarByte(comidIndex,index)*10+getRecvVarBit(comidIndex,index);
        emit signalVarChanged(comidIndex, varoffset, value);
    }
}

unsigned long DataParser::getRecvVarValueByIndex(int comidindex, int index)
{
    if(comidindex < 0 || comidindex > GlobalConfig::recvTRDPList.length() || index == -1)
        return 0;
    return recvVar[comidindex].at(index);
}

unsigned long DataParser::getRecvVarValueByOffset(int comidindex,uint Byte, uint Bit)
{
    return getRecvVarValueByIndex(comidindex,getRecvVarIndex(comidindex,Byte,Bit));
}

int DataParser::getRecvVarIndex(int comidIndex, uint byte, uint bit)
{
    if(comidIndex < 0 || comidIndex > GlobalConfig::recvTRDPList.length())
        return -1;
    for(int i=0;i<GlobalConfig::recvTRDPList.at(comidIndex).node.length();i++)
    {
        if(byte == GlobalConfig::recvTRDPList.at(comidIndex).node.at(i).byte &&
           bit == GlobalConfig::recvTRDPList.at(comidIndex).node.at(i).bit)
            return i;
    }
    return -1;
}

unsigned long DataParser::getRecvVarValue(int comidIndex, int index)
{
    if(trdp->getComState() == TRDPThread::running)
        return recvVar[comidIndex].at(index);
    else
        return 0;
}

int DataParser::getRecvVarCount(int comidIndex)
{
    Q_ASSERT(comidIndex>=0 && comidIndex<GlobalConfig::recvTRDPList.size());
    return GlobalConfig::recvTRDPList[comidIndex].node.size();
}

unsigned int DataParser::getRecvVarByte(int comidIndex, int index)
{
    Q_ASSERT(comidIndex>=0 && comidIndex<GlobalConfig::recvTRDPList.size());
    return GlobalConfig::recvTRDPList[comidIndex].node.at(index).byte;
}

unsigned char DataParser::getRecvVarBit(int comidIndex, int index)
{
    Q_ASSERT(comidIndex>=0 && comidIndex<GlobalConfig::recvTRDPList.size());
    return GlobalConfig::recvTRDPList[comidIndex].node.at(index).bit;
}

unsigned char DataParser::getRecvVarSize(int comidIndex, int index)
{
    Q_ASSERT(comidIndex>=0 && comidIndex<GlobalConfig::recvTRDPList.size());
    return GlobalConfig::recvTRDPList[comidIndex].node.at(index).size;
}

QString DataParser::getRecvVarName(int comidIndex, int index)
{
    Q_ASSERT(comidIndex>=0 && comidIndex<GlobalConfig::recvTRDPList.size());
    return GlobalConfig::recvTRDPList[comidIndex].node.at(index).varName;
}

int DataParser::getSendVarCount(int comidIndex)
{
    Q_ASSERT(comidIndex>=0 && comidIndex<GlobalConfig::sendTRDPList.size());
    return GlobalConfig::sendTRDPList[comidIndex].node.size();
}

unsigned int DataParser::getSendVarByte(int comidIndex, int index)
{
    Q_ASSERT(comidIndex>=0 && comidIndex<GlobalConfig::sendTRDPList.size());
    return GlobalConfig::sendTRDPList[comidIndex].node.at(index).byte;
}

unsigned char DataParser::getSendVarBit(int comidIndex, int index)
{
    Q_ASSERT(comidIndex>=0 && comidIndex<GlobalConfig::sendTRDPList.size());
    return GlobalConfig::sendTRDPList[comidIndex].node.at(index).bit;
}

unsigned char DataParser::getSendVarSize(int comidIndex, int index)
{
    Q_ASSERT(comidIndex>=0 && comidIndex<GlobalConfig::sendTRDPList.size());
    return GlobalConfig::sendTRDPList[comidIndex].node.at(index).size;
}

QString DataParser::getSendVarName(int comidIndex, int index)
{
    Q_ASSERT(comidIndex>=0 && comidIndex<GlobalConfig::sendTRDPList.size());
    return GlobalConfig::sendTRDPList[comidIndex].node.at(index).varName;
}

uint DataParser::getTime()
{
    if(trdp->getComState() != TRDPThread::running)
        return 0xffffffff;
    int year = this->readMemVar(0, 2, 0, 8);
    int month = this->readMemVar(0, 3, 0, 8);
    int day = this->readMemVar(0, 4, 0, 8);
    int hour = this->readMemVar(0, 5, 0, 8);
    int minute = this->readMemVar(0, 6, 0, 8);
    int second = this->readMemVar(0, 7, 0, 8);
    QString str = QString("%1-%2-%3 %4:%5:%6").arg(year+2000, 4, 10, QChar('0')).arg(month, 2, 10, QChar('0')).arg(day, 2, 10, QChar('0')).arg(hour, 2, 10, QChar('0'))\
            .arg(minute, 2, 10, QChar('0')).arg(second, 2, 10, QChar('0'));
    return QDateTime::fromString(str, "yyyy-MM-dd hh:mm:ss").toTime_t();
}

unsigned int DataParser::getSendVarIndex(int comidIndex, uint byte, uint bit)
{
    if(comidIndex < 0 || comidIndex>GlobalConfig::sendTRDPList.length())
        return -1;
    for(int i=0;i<GlobalConfig::sendTRDPList.at(comidIndex).node.length();i++)
    {
        if(byte == GlobalConfig::sendTRDPList.at(comidIndex).node.at(i).byte &&
           bit == GlobalConfig::sendTRDPList.at(comidIndex).node.at(i).bit)
            return i;
    }
    return -1;
}
